<?php

namespace app\model;

use app\common\model\Goods as payGoods;
use think\facade\Db;
use think\facade\Log;
use think\model\concern\SoftDelete;
use app\common\model\Export;
use app\common\model\FinanceStat;

/**
 * 
 *
 * @mixin \think\Model
 * @property int $id
 * @property int $supplier_id 供应商id
 * @property int $supplier_discount 供应商结算折扣（%）
 * @property int $supplier_price 供应商结算价。单位：分
 * @property int $settle_price 代理商结算价。单位：分
 * @property int $profit 代理商利润。单位：分
 * @property int $agent_id 代理商id
 * @property bool $settle_type 代理商结算类型
 * @property int $settle_discount 结算折扣
 * @property int $platform_profit 平台利润。单位：分
 * @property string $order_id 平台订单号
 * @property string $out_order_id 第三方订单信息
 * @property int $origin_amount 原价，单位分
 * @property int $amount 实际价格，单位分
 * @property int $pay_amount 实际支付金额 如果没有优惠抵扣的话=price
 * @property bool $pay_type 支付方式
 * @property bool $pay_status 支付状态 0 未支付 1 已支付
 * @property string $pay_time 支付时间
 * @property bool $refund_status 退款状态 1未退款 2退款中 3已退款
 * @property int $refund_amount 退金额 如果是已退款 并且金额小于pay_amount表示部分退款
 * @property int $user_id 支付用户id
 * @property int $cnid 渠道id
 * @property bool $serv_type 订单业务类型。不同我业务不同取值。type则是在业务下订单类型的区分
 * @property bool $type 订单类型。业务下订单子类型。比如权益订单，不同权益可能需要不同类型标识
 * @property string $settled_at 结算时间
 * @property string $created_at 创建时间
 * @property string $updated_at 更新时间
 * @property string $deleted_at
 * @property int $status 0未提交 1已提交  2提交失败 3充值成功  4充值失败 5订单处理中 10超时关闭
 * @property string $status_msg 状态信息
 * @property string $complete_at 完成时间
 * @property string $supplier_order_sn 供应商返回的订单号
 * @property bool $agent_settle_status 结算状态  1无需结算 2待结算 3已结算
 * @property string $card_info 卡密信息
 * @property-read \app\model\BaseSupplier $supplier
 * @property-read \app\model\Agent $agent
 * @property-read \app\model\GoodsCart $goods_cart
 * @property string $account 充值账号
 * @property string $product_name 产品名称
 * @property string $product_image 产品图片
 * @property string $log 订单日志
 * @property string $supplier_code 供应商代号
 * @property int $salesman_id 业务员
 * @property string $order_created_at 订单创建时间（可能第三方）
 * @property-read string $order_status_text
 * @property-read array $return_status
 * @property mixed $ext_data 扩展信息
 * @property string $title 标题
 * @property string $agent_name 代理商名称
 * @property string $serv_type_name 服务名称
 * @property-read string $agent_company_name
 * @method static \think\db\Query agentId()
 * @property string $curl_date 订单请求第三方更新的时间
 * @property-read \app\model\AgentChannel $agent_channel
 * @property-read \app\model\CouponOrderSid $couponOrderSid
 * @property string $sid 自定义标记信息
 * @property-read \app\model\MobileUser $user
 * @property string $mobile 手机号
 * @property int $quote_id 关联表字段
 * @property int $supplier_status 1 未提交 2 待提交 4 已提交 6 成功 8 失败 99 轮训
 * @property string $remark
 * @property string $pay_log_id
 * @property-read \app\model\CouponProductChannel $couponProductChannel
 * @property-read \app\model\payLog $payLog
 * @property-read \app\model\MovieOrder $movieOrder
 * @property array $premiumRate
 * @property int $new_supplier_price 价格降低时候，供应商结算价。单位：分
 * @property int $brand_id 品牌id
 * @property int $product_id 产品id
 * @property int $order_finish_at 完成时间（第三方供应商确认完成时间）
 * @property int $extension_type 推广类型用于我的推广统计标记  CouponExtension 类中使用枚举
 * @method static \think\db\Query onlyTrashed()
 * @method static \think\db\Query withTrashed()
 */
class CouponOrderOld extends CommonModel
{
    // CouponOrderOld 旧的 不用用这个模型！！！！！！
    protected static $error = '';

    use SoftDelete;
    protected static $statusMsg = [
        10007 => '参数错误！', 10008 => '订单超时！', 10009 => '参数校验错误！', 10010 => '代理商 ID 不存在！', 10011 => '订单号长度大于 36！',
        10012 => '代理商状态错误', 10013 => '账户余额不足', 10014 => 'IP 地址验证失败', 10015 => '充值号码有误', 10016 => '暂不支持该号码',
        10017 => '禁止采购该商品', 10018 => '订单提交成功', 10020 => '订单提交失败', 10021 => '未知错误', 10022 => '订单号重复',
        10023 => '暂不支持该面值', 10025 => '订单处理中', 10026 => '交易失败', 10027 => '交易成功', 10029 => '订单不存在', 10035 => '限制5分钟内同一时间和同一个金额',
        10036 => '系统维护', 10037 => '活动未开始', 10038 => '活动已结束',
    ];

    protected static $payType = [0 => '', 1 => '微信支付', 2 => '支付宝支付', '3' => '后台添加'];





    /**
     * 生成订单编号
     * VD:(视频).
     */
    public static function generateCouponOrderId($sub = '')
    {
        for ($i = 0; $i < 21; ++$i) {
            $orderId = date('ymdHis') . str_pad(mt_rand(0, 99999), 5, STR_PAD_LEFT);
            $id = self::where('order_id', $orderId)->value('id');
            if (empty($id)) {
                return $orderId;
            }
        }

        return false;
    }


    /**
     * 支付回调  和 第三方接口分离
     * @param $payLog
     * @return string|\think\response\Json
     */
    public static function paySuccessNew($payLog)
    {
        $order = self::where('order_id', $payLog['order_id'])
            ->where('pay_status', 0)
            ->findOrEmpty();
        if ($order->isEmpty()) {
            return '支付失败！待支付订单不存在';
        }

        Db::startTrans();
        try {
            $orderId = $payLog['order_id'];
            CouponPayLog::update([
                'status' => 2,
                'trade_no' => $payLog['trade_no'],
                'real_pay_price' => $payLog['real_pay_price'],
            ], ['id' => $payLog['id']]);

            if (SETTLE_TYPE_PREPAY == $payLog['settle_type']) {
                // 如果是预付，需要判断代理商账户余额
                $balance = Agent::where('id', $payLog['agent_id'])
                    ->lock(true)
                    ->value('balance');

                if (empty($balance) || $balance < $payLog['amount']) {
                    $order->status = self::C_STATUS_SUBMIT_FAIL;
                    $order->status_msg = '账户余额不足';
                    $order->refund_status = self::C_REFUND_STATUS_ING;
                } else {
                    $agentAmount = $order['settle_price'];
                    Db::name('agent')
                        ->where('id', $payLog['agent_id'])
                        ->dec('balance', $agentAmount)
                        ->update([
                            'balance_last_updated_at' => date('Y-m-d H:i:s'),
                        ]);

                    $agentBalanceLog = new AgentBalanceLog();
                    $dataLog = [
                        'agent_id' => $payLog['agent_id'],
                        'type' => BALANCE_COUPON_EXPENSE,
                        'amount' => -$agentAmount,
                        'old_balance' => $balance,
                        'new_balance' => $balance - $agentAmount,
                        'remark' => '购买权益会员：原价：' . fen2yuan($payLog['amount']) . '元，结算价：' . yuan2fen($agentAmount) . '，利润：' . yuan2fen($order['profit']) . '。订单号：' . $payLog['order_id'],
                        'quote_id' => $order->id,
                        'trade_no' => $orderId,
                    ];
                    $agentBalanceLog->save($dataLog);
                }
            }

            $order->pay_status = self::C_PAY_STATUS_YES;
            $order->pay_time = date('Y-m-d H:i:s');

            $order->save();

            Db::commit();
            return success('支付成功！');
        } catch (\Exception $e) {
            Db::rollback();

            return fail('导入失败：' . $e->getMessage());
        }
    }

    //支付成功回调
    public static function paySuccess($payLog)
    {
        $order = self::where('order_id', $payLog['order_id'])
            ->where('pay_status', 0)
            ->findOrEmpty();
        if (empty($order)) {
            return fail('支付失败！待支付订单不存在');
        }

        Db::startTrans();
        try {
            $orderId = $payLog['order_id'];
            Db::name('coupon_pay_log')
                ->where('id', $payLog['id'])
                ->update([
                    'status' => 2,
                    'trade_no' => $payLog['trade_no'],
                    'real_pay_price' => $payLog['real_pay_price'],
                ]);
            if (SETTLE_TYPE_PREPAY == $payLog['settle_type']) {
                // 如果是预付，需要判断代理商账户余额
                $balance = Db::name('agent')
                    ->where('id', $payLog['agent_id'])
                    ->lock(true)
                    ->value('balance');
                if (empty($balance) || $balance < $payLog['amount']) {
                    $order->status = 2;
                    $order->status_msg = '账户余额不足';
                    $order->refund_status = 2;
                }
            }
            $order->pay_status = 1;
            $order->pay_time = date('Y-m-d H:i:s');
            $cart = GoodsCart::where('order_id', $order->id)->find();
            $return = [];
            if ($cart && 0 == $order->status) {
                if ('视频接口' == $cart['api_name']) {
                    $return = payGoods::addVideo($cart['sku_id'], $orderId, $cart['account'], $cart['quantity']);
                }
                if ('游戏接口' == $cart['api_name'] && 2 == $cart['sku_type']) {
                    $return = payGoods::addCard(23, $cart['account'], $cart['market_price'], $cart['quantity'], $orderId, $cart['sku_id'], $cart['api_ip']);
                }
                if ('游戏接口' == $cart['api_name'] && 1 == $cart['sku_type']) {
                    $return = payGoods::addCard(45, $cart['account'], $cart['market_price'], $cart['quantity'], $orderId, $cart['sku_id'], $cart['api_ip']);
                }
                if (!empty($return)) {
                    $return = json_decode($return, true);
                    if (isset($return['ReturnOrderID'])) {
                        // 供应商订单号。 sprintf("%.0f", xxx)，避免大整数转成科学计数法
                        $order->supplier_order_sn = sprintf("%.0f", $return['ReturnOrderID']);
                    }
                    //预付的话代理商金额减少
                    if (SETTLE_TYPE_PREPAY == $payLog['settle_type']) {
                        $agentAmount = $order['settle_price'];
                        Db::name('agent')
                            ->where('id', $payLog['agent_id'])
                            ->dec('balance', $agentAmount)
                            ->update([
                                'balance_last_updated_at' => date('Y-m-d H:i:s'),
                            ]);
                        Db::name('agent_balance_log')
                            ->insert([
                                'agent_id' => $payLog['agent_id'],
                                'type' => BALANCE_COUPON_EXPENSE,
                                'amount' => -$agentAmount,
                                'old_balance' => $balance,
                                'new_balance' => $balance - $agentAmount,
                                'remark' => '购买权益会员：原价：' . fen2yuan($payLog['amount']) . '元，结算价：' . yuan2fen($agentAmount) . '，利润：' . yuan2fen($order['profit']) . '。订单号：' . $payLog['order_id'],
                                'quote_id' => $order->id,
                                'trade_no' => $payLog['order_id'],
                            ]);
                    }

                    if ('10018' == $return['Code']) {
                        $order->status = 1;
                    } else {
                        $order->status = 2;
                        //订单状态改成待退款
                        $order->refund_status = 2;
                    }
                    $order->status_msg = isset(self::$statusMsg[$return['Code']]) ? self::$statusMsg[$return['Code']] : '';
                }
            }
            $order->save();
            $result = success('支付成功！');

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            return fail('导入失败：' . $e->getMessage());
        }

        return $result;
    }

    //接口异步回调
    public function orderBack($orderId, $code, $cardInfo)
    {
        $order = self::where('status', 1)->where('order_id', $orderId)->find();
        $payLog = Db::name('coupon_pay_log')->where('order_id', $orderId)->find();
        $balance = Db::name('agent')
            ->where('id', $payLog['agent_id'])
            ->value('balance');
        if (!empty($order)) {
            if ('10027' == $code) {
                $order->status = 3;
            } elseif ('10025' == $code) {
                $order->status = 5;
            } else {
                $order->status = 4;
            }
            $order->status_msg = isset(self::$statusMsg[$code]) ? self::$statusMsg[$code] : '';
            $order->complete_at = date('Y-m-d H:i:s');
            //如果订单充值失败  进入到待退款队列
            if (4 == $order->status) {
                $order->refund_status = 2;
                //  $this->refund($order->id);
            }
            if (3 == $order->status) {
                if (SETTLE_TYPE_PROFIT == $order->settle_type) {
                    //充值成功返佣金
                    Db::name('agent')
                        ->where('id', $order->agent_id)
                        ->inc('profit_balance', $order->profit)
                        ->inc('total_profit', $order->profit)
                        ->update([
                            'balance_last_updated_at' => date('Y-m-d H:i:s'),
                        ]);
                    Db::name('agent_balance_log')
                        ->insert([
                            'agent_id' => $order->agent_id,
                            'type' => BALANCE_COUPON_COMMISS,
                            'amount' => $order->profit,
                            'old_balance' => $balance,
                            'new_balance' => $balance + $order->profit,
                            'remark' => '权益订单完成返佣：' . fen2yuan($order->profit) . '元。订单号：' . $order->order_id,
                            'quote_id' => $payLog['id'],
                            'trade_no' => $payLog['order_id'],
                        ]);
                }

                // 成功了，插入财务明细
                FinanceStat::addSuccessRecord([
                    'order_id' => $order->order_id,
                    'order_type' => PRODUCT_COUPON_SERV,
                    'settle_type' => $order->settle_type,
                    'amount' => $order->amount,
                    'sale_price' => $order->sale_price,
                    'settle_price' => $order->settle_price,
                    'supplier_price' => $order->supplier_price,
                    'profit' => $order->profit,
                    'platform_profit' => $order->platform_profit,
                    'supplier_id' => $order->supplier_id,
                    'agent_id' => $order->agent_id,
                    'remark' => '充值成功',
                ]);
            }
            $order->card_info = json_encode($cardInfo, true);
            $order->save();
        }

        return true;
    }

    /**
     * 总后台查看的订单列表
     */
    public static function getAdminList($params)
    {
        $where = self::setWhere($params);
        $paginate = [
            'page' => $params['page'] ?? 1,
            'list_rows' => $params['list_rows'] ?? 10,
        ];
        $db = self::alias('a')
            ->field('a.*,d.username as agent_name,d.company_name,e.name as supplier_name')
            ->with('agentChannel')
            ->join('agent d', 'd.id =a.agent_id', 'left')
            ->join('base_supplier e', 'e.id =a.supplier_id', 'left')
            ->where($where)
            ->where(['a.serv_type' => PRODUCT_COUPON_SERV])
            ->order('a.id desc');


        // 导出数据字段处理
        if (!empty($params['is_export'])) {
            $list = $db->select()->toArray();
            $res = [];
            $title = ['系统订单号', '供应商订单号', '接口订单号', '商品名称', '销售价', '结算价', '成本价', '代理商利润', '平台利润', '充值号码', '订单状态', '下单时间', '支付时间', '完成时间', '代理商名称', '代理商公司名称', '供应商'];
            foreach ($list as $v) {

                $res[] = [
                    $v['order_id'] . "\t",
                    $v['supplier_order_sn'] . "\t",
                    $v['out_order_id'] . "\t",
                    $v['product_name'],
                    fen2yuan($v['amount']) . '',
                    fen2yuan($v['settle_price']) . '',
                    fen2yuan($v['supplier_price']) . '',
                    fen2yuan($v['profit']) . '',
                    fen2yuan($v['platform_profit']) . '',
                    $v['account'],
                    self::getStatus($v['status'], $v['pay_status'], $v['refund_status']),
                    $v['created_at'],
                    $v['pay_time'],
                    $v['complete_at'],
                    $v['agent_name'],
                    $v['company_name'],
                    $v['supplier_name'],
                ];
            }
            unset($list);
            $export = new Export;
            $name = '权益订单';
            return $export->downloadExcel($title, $res, $name);
        }

        $list = $db->paginate($paginate)->toArray();

        return $list;
    }

    /**
     * 代理商订单列表
     */
    public static function getAgentList($params)
    {
        if (empty($params['agent_id'])) {
            return fail('账号出错！');
        }
        $where = self::setWhere($params);
        $paginate = [
            'page' => $params['page'] ?? 1,
            'list_rows' => $params['list_rows'] ?? 10,
        ];
        $db = self::alias('a')
            ->field('id, order_id, product_name, amount, settle_price, profit, account, status, pay_time, pay_status, refund_status,
            product_name, created_at, settled_at, complete_at, updated_at')
            ->where($where)
            ->where(['a.serv_type' => PRODUCT_COUPON_SERV])
            ->order('a.id desc');

        // 导出数据字段处理
        if (!empty($params['is_export'])) {
            $list = $db->select()->toArray();
            $res = [];
            $title = ['系统订单号', '商品名称', '销售价', '结算价', '利润', '充值号码', '订单状态', '下单时间', '支付时间', '完成时间'];
            foreach ($list as $v) {
                $res[] = [
                    $v['order_id'] . "\t",
                    $v['product_name'],
                    fen2yuan($v['amount']) . '',
                    fen2yuan($v['settle_price']) . '',
                    fen2yuan($v['profit']) . '',
                    $v['account'],
                    self::getStatus($v['status'], $v['pay_status'], $v['refund_status']),
                    $v['created_at'],
                    $v['pay_time'],
                    $v['complete_at'],
                ];
            }
            unset($list);
            $export = new Export;
            $name = '权益订单';
            return $export->downloadExcel($title, $res, $name);
        }

        $list = $db->paginate($paginate)->toArray();

        return $list;
    }

    /**
     * 获取订单状态
     * 前端状态：1待付款 2支付成功 3充值成功 4失败退单 10已关闭
     * 数据库 status 状态：0未提交 1已提交 2提交失败 3充值成功 4充值失败 5订单处理中 10已关闭
     * 数据库 refund_status 退款状态 1未退款 2待退款 3已退款
     * 数据库 pay_status 支付状态 0 未支付 1 已支付
     */
    public static function getStatus($status, $payStatus, $refundStatus)
    {
        if ($status == 10) {
            return '已关闭';
        }
        if ($status == 3) {
            return '充值成功';
        }
        if (in_array($status, [2, 4])) {
            if ($refundStatus == 3) {
                return '退款完成';
            }
            return '失败退款中';
        }
        if ($payStatus == 0) {
            return '待付款';
        }
        if ($payStatus == 1) {
            return '支付成功';
        }
    }

    public static function setWhere($data)
    {
        $where = [];
        // 前端状态：1待付款 2支付成功 3充值成功 4失败退单 10已关闭
        // 数据库 status 状态：0未提交 1已提交 2提交失败 3充值成功 4充值失败 5订单处理中 10超时关闭
        // 数据库 refund_status 退款状态 1未退款 2待退款 3已退款
        // 数据库 pay_status 支付状态 0 未支付 1 已支付
        if (isset($data['status'])) {
            switch ($data['status']) {
                case 1: // 待付款
                    $where[] = ['a.pay_status', '=', 0];
                    $where[] = ['a.status', '=', 0];
                    break;
                case 2: // 支付成功
                    $where[] = ['a.pay_status', '=', 1];
                    $where[] = ['a.status', 'in', [0, 1, 5]];
                    break;
                case 3: // 充值成功
                    $where[] = ['a.status', '=', 3];
                    break;
                case 4: // 失败退单
                    $where[] = ['a.status', 'in', [2, 4]];
                    break;
                case 10: // 已关闭
                    $where[] = ['a.status', '=', 10];
                    break;
            }
        }
        if (isset($data['order_id']) && !empty($data['order_id'])) {
            $where[] = ['a.order_id', 'like', '%' . $data['order_id'] . '%'];
        }
        if (isset($data['product_name']) && !empty($data['product_name'])) {
            $where[] = ['a.product_name', 'like', '%' . $data['product_name'] . '%'];
        }
        if (isset($data['agent_name']) && !empty($data['agent_name'])) {
            $where[] = ['d.username', 'like', '%' . $data['agent_name'] . '%'];
        }
        if (isset($data['supplier_name']) && !empty($data['supplier_name'])) {
            $where[] = ['e.name', 'like', '%' . $data['supplier_name'] . '%'];
        }
        if (isset($data['agent_id']) && !empty($data['agent_id'])) {
            $where[] = ['a.agent_id', '=', $data['agent_id']];
        }
        $createdDate = $data['createdDate'] ?? [];
        if (is_array($createdDate) && !empty($createdDate[0]) && $createdDate[1]) {
            $where[] = ['a.created_at', 'between time', [$createdDate[0], $createdDate[1] . ' 23:59:59']];
        }
        $createdDate = $data['payDate'] ?? [];
        if (is_array($createdDate) && !empty($createdDate[0]) && $createdDate[1]) {
            $where[] = ['a.pay_time', 'between time', [$createdDate[0], $createdDate[1] . ' 23:59:59']];
        }
        $createdDate = $data['completeDate'] ?? [];
        if (is_array($createdDate) && !empty($createdDate[0]) && $createdDate[1]) {
            $where[] = ['a.complete_at', 'between time', [$createdDate[0], $createdDate[1] . ' 23:59:59']];
        }

        return $where;
    }

    /**
     * 前端订单列表
     * 0全部 1待付款 2待发货 3已完成 4已关闭
     * 数据库 status 状态：0未提交 1已提交 2提交失败 3充值成功 4充值失败 5订单处理中 10超时关闭
     * 数据库 refund_status 退款状态 1未退款 2待退款 3已退款
     * 数据库 pay_status 支付状态 0 未支付 1 已支付
     **/
    public static function orderList($data, $userId)
    {
        $where[] = ['user_id', '=', $userId];
        // if (!empty($data['serv_type'])) {
        //     $where[] = ['serv_type', '=', $data['serv_type']];
        // }
        // if (!empty($data['sku_type'])) {
        //     $where[] = ['sku_type', '=', $data['sku_type']];
        // }

        $paginate = [
            'page' => $params['page'] ?? 1,
            'list_rows' => $params['list_rows'] ?? 10,
        ];
        $status = $data['status'] ?? 0;
        $order = self::where($where)
            ->where(function ($query) use ($status) {
                switch ($status) {
                    case 1: // 待付款
                        $query->where('pay_status', 0)
                            ->where('status', 0);
                        break;
                    case 2: // 待发货
                        $query->where('pay_status', 1)
                            ->where('status', 'in', [0, 1, 5]);
                        break;
                    case 3: // 已完成
                        $query->where('status', 3);
                        break;
                    case 4: // 已关闭
                        $query->where('status', 10)
                            ->whereOr('refund_status', 3);
                        break;
                }
            })
            ->field('id, created_at, status, order_id, origin_amount, amount, pay_amount, pay_status, refund_status,supplier_order_sn
            product_name, product_image, pay_time')
            ->where(['serv_type' => PRODUCT_COUPON_SERV])
            ->order('id desc')
            ->paginate($paginate)
            ->toArray();
        foreach ($order['data'] as $nk => $nv) {
            // return_status 状态信息 1待付款 2充值中 3充值成功 4充值失败 5退款中 6 退款成功 10已取消
            $order['data'][$nk]['return_status'] = 1;
            if (0 == $nv['pay_status']) {
                $order['data'][$nk]['return_status'] = 1;
            }
            if (1 == $nv['pay_status'] && in_array($nv['status'], [0, 1, 5])) {
                $order['data'][$nk]['return_status'] = 2;
            }
            if (1 == $nv['pay_status'] && 3 == $nv['status']) {
                $order['data'][$nk]['return_status'] = 3;
            }
            if (1 == $nv['pay_status'] && in_array($nv['status'], [2, 4])) {
                $order['data'][$nk]['return_status'] = 4;
            }
            if (10 == $nv['status']) {
                $order['data'][$nk]['return_status'] = 10;
            }
            if (2 == $nv['refund_status']) {
                $order['data'][$nk]['return_status'] = 5;
            }
            if (3 == $nv['refund_status']) {
                $order['data'][$nk]['return_status'] = 6;
            }
            $order['data'][$nk]['origin_amount'] = fen2yuan($nv['origin_amount']);
            $order['data'][$nk]['amount'] = fen2yuan($nv['amount']);
            $order['data'][$nk]['pay_amount'] = fen2yuan($nv['pay_amount']);
            unset(
                $order['data'][$nk]['status'],
                $order['data'][$nk]['pay_status'],
                $order['data'][$nk]['refund_status']
            );
        }

        return $order;
    }

    /**
     * 前端订单详情.
     */
    public static function orderDetail($data, $userId)
    {
        if (empty($data['order_id'])) {
            return fail('订单号不能为空');
        }
        $order = self::where('order_id', $data['order_id'])
            ->where("user_id", $userId)
            ->field('id, created_at, order_id, account, origin_amount, amount, pay_amount, pay_type, status, pay_status,
            refund_status, card_info, product_name, product_image, pay_time')
            ->find();
        if (empty($order)) {
            return fail('订单编号错误！');
        }
        $order = $order->toArray();
        // return_status 状态信息 1待付款 2充值中 3充值成功 4充值失败 5退款中 6 退款成功 10已取消
        $order['return_status'] = 1;
        if (0 == $order['pay_status']) {
            $order['return_status'] = 1;
        }
        if (1 == $order['pay_status'] && in_array($order['status'], [0, 1, 5])) {
            $order['return_status'] = 2;
        }
        if (1 == $order['pay_status'] && 3 == $order['status']) {
            $order['return_status'] = 3;
        }
        if (1 == $order['pay_status'] && in_array($order['status'], [2, 4])) {
            $order['return_status'] = 4;
        }
        if (10 == $order['status']) {
            $order['return_status'] = 10;
        }
        if (2 == $order['refund_status']) {
            $order['return_status'] = 5;
        }
        if (3 == $order['refund_status']) {
            $order['return_status'] = 6;
        }
        $countDown = 0;
        if ($order['status'] != 10) {
            if ($order['pay_status'] == 0) {
                $cha = floor((time() - strtotime($order['created_at'])) % 86400);
                if ($cha < 1800) {
                    $countDown = 1800 - $cha;
                } else {
                    //自动取消
                    Db::name("coupon_order")->where("id", $order['id'])->update(['status' => 10]);
                    Db::name("coupon_pay_log")->where("order_id", $order['order_id'])->update(['status' => 3]);
                    $order['return_status'] = 10;
                }
            }
        }
        $order['countdown'] = $countDown;
        $order['origin_amount'] = fen2yuan($order['origin_amount']);
        $order['amount'] = fen2yuan($order['amount']);
        $order['pay_amount'] = fen2yuan($order['pay_amount']);
        unset(
            $order['status'],
            $order['pay_status'],
            $order['refund_status'],
        );
        return success('成功！', $order);
    }

    public static function getError()
    {
        return self::$error;
    }

    /**
     * 退款.
     */
    public function refund($id)
    {
        $order = Db::name('coupon_order')
            ->where('id', $id)
            ->find();
        if (empty($order)) {
            $this->error = '订单不存在';

            return false;
        }

        if (0 == $order['pay_status']) {
            $this->error = '该订单尚未支付';

            return false;
        }
        if (!in_array($order['status'], [2, 4])) {
            $this->error = '充值失败的订单才能退款【' . $order['status'] . '】';

            return false;
        }
        if (2 != $order['refund_status']) {
            $this->error = '退款状态有误【' . $order['refund_status'] . '】';

            return false;
        }
        $refundSettleFee = $order['settle_price'];
        $payLog = Db::name('coupon_ pay_log')
            ->where('order_id', $order['order_id'])
            ->where('status', 2)
            ->find();
        if (empty($payLog)) {
            $this->error = '支付记录不存在';

            return false;
        }
        if (empty($payLog['real_pay_price']) || empty($payLog['trade_no'])) {
            $this->error = '支付记录异常';

            return false;
        }

        // 金额原路退给用户
        $refundFee = $payLog['real_pay_price'];
        $payLog['refund_fee'] = $refundFee;
        $res = $this->wxpayRefund($payLog);
        if (false === $res) {
            return false;
        }

        Db::startTrans();
        try {
            $flag = Db::name('coupon_order')
                ->where('id', $order['id'])
                ->where('refund_status', 2)
                ->update([
                    'refund_status' => 3,
                ]);
            if ($flag) {
                Db::rollback();

                $this->error = '退款失败: 退款状态有误';
                return false;
            }

            // 代理商扣款记录
            $payAmount = Db::name('agent_balance_log')
                ->where('type', BALANCE_COUPON_EXPENSE)
                ->where('quote_id', $order['id'])
                ->value('amount');
            // 代理商退款记录
            $refund = Db::name('agent_balance_log')
                ->where('type', BALANCE_COUPON_REFUND)
                ->where('quote_id', $order['id'])
                ->value('id');
            // 有扣款，没退款，就开始退
            if ($payAmount && empty($refund)) {
                $payAmount = abs($payAmount);
                if ($payAmount != $refundSettleFee) {
                    Db::rollback();
                    $this->error = '退款金额有误';
                    return false;
                }
                $balance = Db::name('agent')
                    ->where('id', $order['agent_id'])
                    ->value('balance');
                $newBalance = $balance + $refundSettleFee;
                Db::name('agent')
                    ->where('id', $order['agent_id'])
                    ->inc('balance', $refundSettleFee)
                    ->update([
                        'balance_last_updated_at' => date('Y-m-d H:i:s'),
                    ]);
                Db::name('agent_balance_log')
                    ->insert([
                        'agent_id' => $order['agent_id'],
                        'type' => BALANCE_COUPON_REFUND,
                        'amount' => $refundSettleFee,
                        'old_balance' => $balance,
                        'new_balance' => $newBalance,
                        'remark' => '权益充值失败退款：' . fen2yuan($refundSettleFee) . ' 元。订单号：' . $order['order_id'],
                        'quote_id' => $order['id'],
                        'trade_no' => $order['order_id'],
                    ]);
            }
            if (SETTLE_TYPE_PROFIT == $order['settle_type']) {
                Db::name('coupon_pay_log')
                    ->where('id', $payLog['id'])
                    ->inc('refund_amount', $refundFee)
                    ->update();
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            $this->error = '退款失败：' . $e->getMessage();

            return false;
        }

        return true;
    }

    /**
     * 微信退款.
     */
    private function wxpayRefund($payLog)
    {
        try {
            if (SETTLE_TYPE_PREPAY == $payLog['settle_type']) {
                $wxpay = new \app\common\model\WxpayV2($payLog['agent_id']);
            } else {
                $type = 'wechat';
                if ('MWEB' == $payLog['trade_type']) {
                    $type = 'wechat_mweb';
                }
                $wxpay = new \app\common\model\WxpayV2(0, $type);
            }
            $data = [
                'transactionId' => $payLog['trade_no'],
                'refundNumber' => $payLog['order_id'],
                'totalFee' => $payLog['real_pay_price'],
                'refundFee' => $payLog['refund_fee'],
                'desc' => '充值失败退款',
            ];
            $res = $wxpay->refund($data);
        } catch (\Exception $e) {
            $this->error = $e->getMessage();

            return false;
        }
        if (isset($res['err_code_des']) && $res['err_code_des'] == '订单已全额退款') {
            return true;
        }
        if (!isset($res['result_code']) || 'SUCCESS' != $res['result_code']) {
            $this->error = '退款失败：' . json_encode($res, JSON_UNESCAPED_UNICODE);

            return false;
        }

        return true;
    }

    /**
     * 场景：CPS 订单详情页，点击 再次购买，进入商品详情页
     */
    public static function getProductUrl($params)
    {
        if (empty($params['order_id'])) {
            self::$error = '订单号不能为空';
            return false;
        }
        if (empty($params['agent_id'])) {
            self::$error = '代理商id不能为空';
            return false;
        }

        $where = [
            ['order_id', '=', $params['order_id']],
            ['agent_id', '=', $params['agent_id']],
        ];
        $order = self::where($where)->find();
        if ($order->isEmpty()) {
            self::$error = '订单不存在';
            return false;
        }

        // 供应商产品id
        $productId = Db::name('coupon_product_channel')
            ->where('supplier_id', $order->supplier->id)
            ->where('name', $order['product_name'])
            ->value('origin_id');
        if (empty($productId)) {
            self::$error = '该产品已下架';
            return false;
        }

        try {
            $class = '\\api\\coupon\\' . ucfirst($order->supplier->code);
            $supplier = new $class;
            $url = $supplier->productUrl($productId, [
                'agent_id' => $params['agent_id'],
                'user_id' => $params['user_id'],
            ]);
            if (empty($url)) {
                self::$error = '链接获取失败';
                return false;
            }
        } catch (\Exception $e) {
            self::$error = $e->getMessage();
            return false;
        }

        return compact('url');
    }







}
